package com.hk.core.service.reactive;

import com.hk.commons.query.Order;
import com.hk.commons.query.QueryModel;
import com.hk.commons.query.page.QueryPage;
import com.hk.commons.util.ArrayUtils;
import org.springframework.data.domain.Persistable;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.io.Serializable;
import java.util.Optional;
import java.util.function.UnaryOperator;

/**
 * @author Kevin
 * @date 2022-07-05 19:53
 */
public interface ReactiveBaseService<T extends Persistable<ID>, ID extends Serializable> {

    Mono<Void> deleteById(ID id);

    Mono<Void> deleteAllById(Iterable<ID> ids);

    /**
     * 会根据 实体 id 删除 ， 实体id 不能为空
     *
     * @param entity entity
     */
    Mono<Void> delete(T entity);

    /**
     * 会根据 实体 id 删除 ， 实体id 不能为空
     *
     * @param entities entities
     */
    Mono<Void> delete(Iterable<T> entities);

    /**
     * 实体保存
     *
     * @param t t
     * @return T
     */
    default Mono<T> insert(T t) {
        return this.insert(t, UnaryOperator.identity());
    }

    default Mono<T> insertOrUpdate(T t) {
        return t.isNew() ? insert(t) : updateById(t);
    }

    Mono<T> insert(T t, UnaryOperator<T> operator);

    /**
     * 实体批量保存
     *
     * @param entities entities
     * @return {@link Iterable}
     */
    Flux<T> batchInsert(Iterable<T> entities);


    /**
     * 根据主键更新
     *
     * @param t t
     * @return t
     */
    default Mono<T> updateById(T t) {
        return updateById(t, UnaryOperator.identity());
    }

    /**
     * 更新
     *
     * @param t        t
     * @param function function
     * @return T
     */
    Mono<T> updateById(T t, UnaryOperator<T> operator);


    /**
     * @param id id
     * @return {@link Optional}
     */
    Mono<T> findById(ID id);

    /**
     * 查询所有
     *
     * @param orders 排序
     * @return {@link Iterable}
     */
    Flux<T> findAll(Order... orders);

    /**
     * @param ids ids
     * @return {@link Iterable}
     */
    Flux<T> findByIds(Iterable<ID> ids);

    /**
     * @param ids ids
     * @return {@link Iterable}
     */
    default Flux<T> findByIds(ID... ids) {
        return ArrayUtils.isEmpty(ids) ? Flux.empty()
                : this.findByIds(ArrayUtils.asArrayList(ids));
    }

    /**
     * 分页查询
     *
     * @param query 查询参数
     * @return {@link QueryPage}
     */
    Mono<QueryPage<T>> queryForPage(QueryModel<T> query);

    /**
     * @param id id
     * @return boolean
     */
    Mono<Boolean> existsById(ID id);

    /**
     * @param t t
     * @return boolean
     */
    Mono<Boolean> exists(T t);

    /**
     * @return long
     */
    Mono<Long> count();

    /**
     * @return long
     */
    Mono<Long> count(T t);
}
